# -!- coding: utf-8 -!-
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#作者：cacho_37967865
#博客：https://blog.csdn.net/sinat_37967865
#文件：getInterest.py
#日期：2019-09-02
#备注：多种利息计算方式，pip install PrettyTable 输出表格格式，decimal模块ROUND_HALF_UP函数进行四舍五入  
#     总逻辑：term_amt计算固定,prin计算固定,term_prin,term_int可变
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
from decimal import Decimal

from prettytable import PrettyTable
import copy
from pycacho.cachobase.deal_float import float_deal      # Decimal格式
from pycacho.cachobase.deal_time import date_calculate,next_date_fixed


principal = Decimal('880.00')     # 本金
annual_rate = Decimal('0.115')      # 年化利率
term_rate = annual_rate / Decimal('12')  # 月利率
day_rate = annual_rate / Decimal('12') /Decimal('30')  # 日利率
pay_date = '2020-05-18'            # 放款成功时间
pay_day = 1                        # 每月2号


repayPattern = {
    "MCAT": "随借随还,按日计息",
    "BFTO": "利随本清,按日计息",
    "MIRD": "按月付息到期还本",
    "EPEI": "等本等息,按月付息",             # 对借款人最不利
    "MCEP": "等额本金,按月付息",             # 借款总利息最低
    "MCEI": "等额等息,按月付息"
}

line = PrettyTable(["期数", "到期还款日","还款本息", "当期本金", "当期利息","剩余本金","还款方式"])

#line.align["期数"] = "1"  # 以期数字段左对齐
#line.padding_width = 2    # 填充宽度(字段间隔)


# "EPEI": "等本等息,按月付息"               每期利息和本金一样,最后一期本金为上一期的剩余本金，最后一期利息为总利息-已还利息
def get_EPEI(num):
    show = copy.deepcopy(line)
    term_int = float_deal(principal * term_rate)         # 每期还利息（2位小数）
    total_int = float_deal(principal*term_rate*num)     # 总利息（2位小数）
    term_prin = float_deal(principal / num)             # 每期还本金（2位小数）
    prin = principal                                    # 初始化剩余本金为借款本金
    for i in range(1,num+1):
        due_date = next_date_fixed(pay_date,i,pay_day)
        # 如果是最后一期，还款本金为上一期的剩余本金; 利息为总利息-已还利息
        if i == num:
            term_prin = prin
            term_int = total_int - (term_int*(num-1))
        term_amt = term_prin + term_int
        prin = prin - term_prin                               # 剩余本金=上期剩余本金-当期还本金
        show.add_row([i, due_date,term_amt, term_prin, term_int, prin,'EPEI'])
    print('等本等息总利息为：',total_int)
    print('对应年化利息为：',float_deal(total_int/principal*12/num*100),'%')
    print(show)


# "MIRD": "按月付息到期还本"      最后一期还本金，每期利息固定
def get_MIRD(num):
    show = copy.deepcopy(line)
    term_int = float_deal(principal*term_rate)
    term_prin = float_deal(0.0)
    total_int = float_deal(principal * term_rate * num)  # 总利息（2位小数）
    prin = principal
    for i in range(1,num+1):
        due_date = date_calculate(pay_date,i)
        # 如果是最后一期，还款本金为上一期的剩余本金; 利息为总利息-已还利息
        if i == num:
            term_prin = prin
            term_int = total_int - (term_int*(num-1))
        term_amt = term_prin + term_int
        prin = prin - term_prin                                        # 剩余本金=上期剩余本金-当期还本金
        show.add_row([i, due_date,term_amt, term_prin, term_int, prin, 'MIRD'])
    print('按月付息到期还本总利息为：', total_int)
    print('对应年化利息为：',float_deal(total_int/principal*12/num*100),'%')
    print(show)


# "等额本金,按月付息"
def get_MCEP(num):
    ## 每月本金相同，利息递减，相当于剩余本金的利息,每期利息固定：上一期本金*利率
    show = copy.deepcopy(line)
    term_prin = float_deal(principal / num)               # 每期还本金（2位小数）
    prin = principal
    total_int = float_deal(0.0)
    for i in range(1, num + 1):
        due_date = date_calculate(pay_date,i)
        term_int = float_deal(prin * term_rate)          # 每期利息固定：上一期本金*利率
        # 如果是最后一期，还款本金为上一期的剩余本金;
        if i == num:
            term_prin = prin
        term_amt = term_prin + term_int
        prin = prin - term_prin                  # 剩余本金=上期剩余本金-当期还本金
        show.add_row([i, due_date, term_amt, term_prin, term_int, prin,'MCEP'])
        total_int = float_deal(total_int +  term_int)
    print('等额本金总利息为：', total_int)
    print('对应年化利息为：',float_deal(total_int/principal*12/num*100),'%')
    print(show)


# "MCEI": "等额本息,按月付息"
def get_MCEI(num):
    # 本金+利息保持相同，本金逐月递增，利息逐月递减，月还款数不变。
    show = copy.deepcopy(line)
    term_amt = float_deal((principal*term_rate*(1+term_rate)**num)/((1+term_rate)**num-1))      # 每期还款总额       **是幂运算
    prin = principal
    total_int = float_deal(0.0)
    for i in range(1, num + 1):
        due_date = date_calculate(pay_date,i)
        term_int = float_deal(prin * term_rate)        # 每期利息计算固定：上一期本金*利率
        term_prin = term_amt - term_int
        # 如果是最后一期，还款本金为上一期的剩余本金;
        if i == num:
            term_prin = prin
        term_amt = term_prin + term_int
        prin = prin - term_prin             # 剩余本金=上期剩余本金-当期还本金
        show.add_row([i, due_date, term_amt, term_prin, term_int,prin,'MCEI'])
        total_int = total_int +  term_int
    print('等额本息总利息为：', total_int)
    print('对应年化利息为：',float_deal(total_int/principal*12/num*100),'%')
    print(show)


# "MCAT": "随借随还,按日计息"
def get_MCAT(num,pay):
    show = copy.deepcopy(line)
    day_int = float_deal(pay*day_rate*num)
    repay_amt = day_int + pay
    re_prin = principal-pay
    due_date = date_calculate(pay_date, num)
    if pay>principal:
        print("还款金额:",pay,"不能大于本金:",principal)
    else:
        show.add_row([1, due_date,repay_amt, pay, day_int, re_prin, 'MCAT'])
        print('随借随还总利息为：', day_int)
        print(show)


# "BFTO": "利随本清,按日计息"
def get_BFTO(num):
    show = copy.deepcopy(line)
    day_int = float_deal(principal*day_rate*num)
    repay_amt = day_int + principal
    due_date = date_calculate(pay_date, num)
    show.add_row([1, due_date, repay_amt, principal, day_int, 0.0, 'BFTO'])
    print('利随本清总利息为：', day_int)
    print(show)


if __name__ == '__main__':
    get_MCEI(24)          # 等额本息,按月付息
    get_EPEI(24)          # 等本等息,按月付息
    get_MIRD(24)          # 到期还本,按月付息
    get_MCEP(24)          # 等额本金,按月付息
    get_MCAT(720,195)     # 随借随还,按日计息
    get_BFTO(720)         # 利随本清,按日计息